/*******************************************************************************
 * Copyright(c) 2023 Levetop Semiconductor Co.,Led. All rights reserved.
 * @file     function.c
 * @author   UartTFT Application Team
 * @version  V0.0.1
 * @date     2023-01-02
 * @brief
 ********************************************************************************/

#include "function.h"
#include <math.h>
#include <stdlib.h>
#include "sincos_table.h"
#include "font.h"
#include "tftlcd.h"
#include "transport.h"
#include "levetop.h"

/***************Convert 24-bit color depth to 16-bit******************************
 * Function Name	: LT_Color24_To_16
 * Description  	: Convert 24-bit color depth to 16-bit.
 * Input        	: - color: 24-bit color
 * Output       	: None
 * Return       	: None
 *********************************************************************************/
uint16_t LT_Color24_To_16(uint32_t color)
{
	uint16_t r, g, b;

	r = ((color >> 19) & 0x1f);
	g = ((color >> 10) & 0x3f);
	b = ((color >> 3) & 0x1f);

	return ((r << 11) + (g << 5) + b);
}

//----------------------------------------------------------------------2D drawing function-------------------------------------------------------------------
/********************************************************************************
* Function Name	: LT268_TFT_DrawPoint
* Description  	: Draw a point on the screen.
* Input        	: - x,y: coordinates of point on the screen
				  - color: point color
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawPoint(uint16_t x, uint16_t y, uint16_t color)
{
	LT268_TFT_SetWindows(x, y, 1, 1);
	LCD_RS_DATA;
	LCD_CS_RESET;
	TFT_Data_Tran2(color, 1);
	LCD_CS_SET;
}

/********************************************************************************
* Function Name	: LT268_TFT_FillColor
* Description  	: Draw a solid rectangle on the screen.
* Input        	: - x,y,w,h: coordinates and size of the rectangle
				  - color: color of the rectangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_FillColor(uint16_t x, uint16_t y, uint16_t Width, uint16_t High, uint16_t color)
{
	uint32_t i = 0;

	LT268_TFT_SetWindows(x, y, Width, High);
	// LCD_RD_SET;
	LCD_RS_DATA;
	LCD_CS_RESET;
	TFT_Data_Tran2(color, Width * High);
	LCD_CS_SET;
}

/********************************************************************************
* Function Name	: LT268_TFT_Draw_hline
* Description  	: Draw a horizontal line.
* Input        	: - x,y,len: coordinates and lenght of the horizontal line
				  - color: color of the horizontal line
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_Draw_hline(uint16_t x0, uint16_t y0, uint16_t len, uint16_t color)
{
	if ((len == 0) || (x0 > LCD_XSIZE_TFT - 1) || (y0 > LCD_YSIZE_TFT - 1))
		return;
	LT268_TFT_FillColor(x0, y0, len, 1, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_Draw_vline
* Description  	: Draw a vertical line.
* Input        	: - x,y,len: coordinates and lenght of the vertical line
				  - color: color of the vertical line
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_Draw_vline(uint16_t x0, uint16_t y0, uint16_t len, uint16_t color)
{
	if ((len == 0) || (x0 > LCD_XSIZE_TFT - 1) || (y0 > LCD_YSIZE_TFT - 1))
		return;
	LT268_TFT_FillColor(x0, y0, 1, len, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawLine
* Description  	: Draw a line.
* Input        	: - x1,y1,x2,y2: two endpoints of the line
				  - color: color of the line
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
	uint16_t t;
	int32_t xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int32_t incx, incy, uRow, uCol;

	delta_x = x2 - x1; // Calculate coordinate increments
	delta_y = y2 - y1;
	uRow = x1;
	uCol = y1;

	// Set single step direction
	if (delta_x > 0)
		incx = 1;
	else if (delta_x == 0)
		incx = 0; // vertical line
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}

	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; // horizontal line
	else
	{
		incy = -1;
		delta_y = -delta_y;
	}

	if (delta_x > delta_y) // Select basic incremental coordinate axis
		distance = delta_x;
	else
		distance = delta_y;

	for (t = 0; t <= distance + 1; t++) // Line drawing output
	{
		LT268_TFT_DrawPoint(uRow, uCol, color); // draw points
		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawLine_Width
* Description  	: Draw a line with width.
* Input        	: - x1,y1,x2,y2: two endpoints of the line
				  - color: color of the line
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawLine_Width(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, uint16_t Width)
{
	uint16_t i;

	if (x2 == x1)
	{
		while (Width--)
		{
			LT268_TFT_DrawLine(x1 + i, y1, x2 + i, y2, color);
			i++;
		}
	}
	else if (y2 == y1)
	{
		while (Width--)
		{
			LT268_TFT_DrawLine(x1, y1 - i, x2, y2 - i, color);
			i++;
		}
	}
	else
	{
		Width = (uint16_t)sqrt(pow((Width * abs(x2 - x1) / abs(y2 - y1)), 2) + pow(Width, 2)) + 1;
		while (Width--)
		{
			LT268_TFT_DrawLine(x1 + i, y1, x2 + i, y2, color);
			i++;
		}
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawSquare
* Description  	: Draw an unfilled rectangle.
* Input        	: - x1,y1,x2,y2: two endpoints of the diagonal line
				  - color: color of the rectangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawSquare(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
	LT268_TFT_DrawLine(x1, y1, x2, y1, color);
	LT268_TFT_DrawLine(x1, y1, x1, y2, color);
	LT268_TFT_DrawLine(x1, y2, x2, y2, color);
	LT268_TFT_DrawLine(x2, y1, x2, y2, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawSquare_Fill
* Description  	: Draw filled rectangle.
* Input        	: - x1,y1,x2,y2: two endpoints of the diagonal line
				  - color: color of the rectangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawSquare_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
{
	uint16_t temp = 0;
	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}
	LT268_TFT_FillColor(x1, y1, x2 - x1 + 1, y2 - y1 + 1, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawSquare_Width
* Description  	: Draw a filled rectangle with a wireframe.
* Input        	: - x1,y1,x2,y2: two endpoints of the diagonal line
				  - WidthColor: color of the wireframe
				  - BackgroundColor: color of the rectangle
				  - Width: Width of wireframe
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawSquare_Width(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t WidthColor, uint16_t BackgroundColor, uint16_t Width)
{
	uint16_t temp = 0;
	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}
	LT268_TFT_DrawSquare_Fill(x1 - Width, y1 - Width, x2 + Width, y2 + Width, WidthColor);
	LT268_TFT_DrawSquare_Fill(x1, y1, x2, y2, BackgroundColor);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircleSquare
* Description  	: Draw rounded rectangle without filling.
* Input        	: - x1,y1,x2,y2: diagonal endpoint
				  - r: circle radius
				  - color: rectangle color
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircleSquare(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t r, uint16_t color)
{
	uint16_t temp;
	uint16_t btnxh = 0;
	uint16_t width, height;

	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}

	width = x2 - x1 + 1;
	height = y2 - y1 + 1;

	if (height % 2)
		btnxh = height + 1; // Base even processing
	else
		btnxh = height;

	LT268_TFT_Draw_hline(x1 + r, y1, width - 2 * r, color);				// up
	LT268_TFT_Draw_hline(x1 + r, y1 + btnxh - 1, width - 2 * r, color); // down
	LT268_TFT_Draw_vline(x1, y1 + r, btnxh / 2 - r, color);				// Upper left
	LT268_TFT_Draw_vline(x1, y1 + btnxh / 2, btnxh / 2 - r, color);		// Lower left
	LT268_TFT_Draw_vline(x2, y1 + r, btnxh / 2 - r, color);				// Upper right
	LT268_TFT_Draw_vline(x2, y1 + btnxh / 2, btnxh / 2 - r, color);		// lower right

	gui_draw_arc(x1, y1, x1 + r, y1 + r, x1 + r, y1 + r, r, color, 0);															   // Upper left
	gui_draw_arc(x1, y1 + btnxh - r, x1 + r, y1 + btnxh - 1, x1 + r, y1 + btnxh - r - 1, r, color, 0);							   // Lower left
	gui_draw_arc(x1 + width - r, y1, x1 + width, y1 + r, x1 + width - r - 1, y1 + r, r, color, 0);								   // Upper right
	gui_draw_arc(x1 + width - r, y1 + btnxh - r, x1 + width, y1 + btnxh - 1, x1 + width - r - 1, y1 + btnxh - r - 1, r, color, 0); // lower right
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircleSquare_Fill
* Description  	: Draw a rounded rectangle with fill.
* Input        	: - x1,y1,x2,y2: diagonal endpoint
				  - r: circle radius
				  - color: rectangle color
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircleSquare_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t r, uint16_t color)
{
	uint16_t temp;
	uint16_t btnxh = 0;
	uint16_t width, height;

	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}

	width = x2 - x1 + 1;
	height = y2 - y1 + 1;

	if (height % 2)
		btnxh = height + 1; // Base even processing
	else
		btnxh = height;

	LT268_TFT_FillColor(x1 + r, y1, width - 2 * r, btnxh / 2, color);			  // Upper-middle
	LT268_TFT_FillColor(x1 + r, y1 + btnxh / 2, width - 2 * r, btnxh / 2, color); // lower-middle
	LT268_TFT_FillColor(x1, y1 + r, r, btnxh / 2 - r, color);					  // Upper left
	LT268_TFT_FillColor(x1, y1 + btnxh / 2, r, btnxh / 2 - r, color);			  // Lower left
	LT268_TFT_FillColor(x1 + width - r, y1 + r, r, btnxh / 2 - r, color);		  // Upper right
	LT268_TFT_FillColor(x1 + width - r, y1 + btnxh / 2, r, btnxh / 2 - r, color); // lower right

	gui_draw_arc(x1, y1, x1 + r, y1 + r, x1 + r, y1 + r, r, color, 1);															   // Upper left
	gui_draw_arc(x1, y1 + btnxh - r, x1 + r, y1 + btnxh - 1, x1 + r, y1 + btnxh - r - 1, r, color, 1);							   // Lower left
	gui_draw_arc(x1 + width - r, y1, x1 + width, y1 + r, x1 + width - r - 1, y1 + r, r, color, 1);								   // Upper right
	gui_draw_arc(x1 + width - r, y1 + btnxh - r, x1 + width, y1 + btnxh - 1, x1 + width - r - 1, y1 + btnxh - r - 1, r, color, 1); // lower right
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircleSquare_Width
* Description  	: Draw a filled rounded rectangle with wireframe.
* Input        	: - x1,y1,x2,y2: diagonal endpoint
				  - r: circle radius
				  - WidthColor: wireframe color
				  - BackgroundColor: rounded rectangle color
				  - Width: wireframe color
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircleSquare_Width(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint8_t r, uint16_t WidthColor, uint16_t BackgroundColor, uint16_t Width)
{
	uint16_t temp;
	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}
	LT268_TFT_DrawCircleSquare_Fill(x1 - Width, y1 - Width, x2 + Width, y2 + Width, r, WidthColor);
	LT268_TFT_DrawCircleSquare_Fill(x1, y1, x2, y2, r, BackgroundColor);
}

void _draw_circle_8(int32_t xc, int32_t yc, int32_t x, int32_t y, uint16_t color)
{
	LT268_TFT_DrawPoint(xc + x, yc + y, color);
	LT268_TFT_DrawPoint(xc - x, yc + y, color);
	LT268_TFT_DrawPoint(xc + x, yc - y, color);
	LT268_TFT_DrawPoint(xc - x, yc - y, color);
	LT268_TFT_DrawPoint(xc + y, yc + x, color);
	LT268_TFT_DrawPoint(xc - y, yc + x, color);
	LT268_TFT_DrawPoint(xc + y, yc - x, color);
	LT268_TFT_DrawPoint(xc - y, yc - x, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircle
* Description  	: Draw an unfilled circle.
* Input        	: - xc,yc,r: centre point and radius of the circle
				  - color: color of the circle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircle(uint16_t xc, uint16_t yc, uint16_t r, uint16_t color)
{
	int32_t x = 0, y = r, d;
	d = 3 - 2 * r;

	while (x <= y)
	{
		_draw_circle_8(xc, yc, x, y, color);
		if (d < 0)
		{
			d = d + 4 * x + 6;
		}
		else
		{
			d = d + 4 * (x - y) + 10;
			y--;
		}
		x++;
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircle_Fill
* Description  	: Draw a filled circle.
* Input        	: - xc,yc,r: centre point and radius of the circle
				  - color: color of the circle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircle_Fill(uint16_t xc, uint16_t yc, uint16_t r, uint16_t color)
{
	uint32_t i;
	uint32_t imax = ((uint32_t)r * 707) / 1000 + 1;
	uint32_t sqmax = (uint32_t)r * (uint32_t)r + (uint32_t)r / 2;
	uint32_t x = r;
	LT268_TFT_Draw_hline(xc - r, yc, 2 * r, color);
	for (i = 1; i <= imax; i++)
	{
		if ((i * i + x * x) > sqmax)
		{
			// draw lines from outside
			if (x > imax)
			{
				LT268_TFT_Draw_hline(xc - i + 1, yc + x, 2 * (i - 1), color);
				LT268_TFT_Draw_hline(xc - i + 1, yc - x, 2 * (i - 1), color);
			}
			x--;
		}
		// draw lines from inside (center)
		LT268_TFT_Draw_hline(xc - x, yc + i, 2 * x, color);
		LT268_TFT_Draw_hline(xc - x, yc - i, 2 * x, color);
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCircle_Width
* Description  	: Draw a filled circle with wireframe.
* Input        	: - xc,yc,r: centre point and radius of the circle
				  - WidthColor: color of the wireframe
				  - BackgroundColor: color of the circle
				  - Width: Width of the wireframe
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawCircle_Width(uint16_t xc, uint16_t yc, uint16_t r, uint16_t WidthColor, uint16_t BackgroundColor, uint16_t Width)
{
	LT268_TFT_DrawCircle_Fill(xc, yc, r + Width, WidthColor);
	LT268_TFT_DrawCircle_Fill(xc, yc, r, BackgroundColor);
}

/********************************************************************************
* Function Name	: LT268_TFT_Draw_expoint
* Description  	: Draw a point in the area.
* Input        	: - sx,sy,ex,ey: area
				  - x,y: point coordinates
				  - color: point color
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_Draw_expoint(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t x, uint16_t y, uint16_t color)
{
	if (x <= ex && x >= sx && y <= ey && y >= sy)
	{
		LT268_TFT_DrawPoint(x, y, color);
	}
}

/********************************************************************************
* Function Name	: gui_draw_circle8
* Description  	: Draw 8 points (Bresenham algorithm).
* Input        	: - sx,sy,ex,ey: area
				  - rx,ry: point coordinates
				  - a,b: point lenght
				  - color: point color
* Output       	: None
* Return       	: None
*********************************************************************************/
void gui_draw_circle8(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t rx, uint16_t ry, int32_t a, int32_t b, uint16_t color)
{
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx + a, ry - b, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx + b, ry - a, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx + b, ry + a, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx + a, ry + b, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx - a, ry + b, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx - b, ry + a, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx - b, ry - a, color);
	LT268_TFT_Draw_expoint(sx, sy, ex, ey, rx - a, ry - b, color);
}

/********************************************************************************
* Function Name	: gui_draw_arc
* Description  	: Draw a circle of the specified size at the specified position.
* Input        	: - sx,sy,ex,ey: area
				  - rx,ry,r: centre point and radius of the circle
				  - color: point color
				  - mode: 0: not filled, 1: Fill
* Output       	: None
* Return       	: None
*********************************************************************************/
void gui_draw_arc(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t rx, uint16_t ry, uint16_t r, uint16_t color, uint8_t mode)
{
	int32_t a, b, c;
	int32_t di;
	a = 0;
	b = r;
	di = 3 - (r << 1); // Mark to judge the position of the next point
	while (a <= b)
	{
		if (mode)
			for (c = a; c <= b; c++)
				gui_draw_circle8(sx, sy, ex, ey, rx, ry, a, c, color); // Draw a solid circle
		else
			gui_draw_circle8(sx, sy, ex, ey, rx, ry, a, b, color); // Draw a hollow circle
		a++;
		// Draw a circle using Bresenham algorithm
		if (di < 0)
			di += 4 * a + 6;
		else
		{
			di += 10 + 4 * (a - b);
			b--;
		}
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawEllipse
* Description  	: Draw a hollow ellipse.
* Input        	: - x0,y0: central coordinate of ellipse
				  - rx,ry: ellipse radius in xy direction
				  - color: color of ellipse
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, uint16_t color)
{
	uint32_t OutConst, Sum, SumY;
	uint16_t x, y;
	uint16_t xOld;
	uint32_t _rx = rx;
	uint32_t _ry = ry;
	if (rx > x0 || ry > y0)
		return;												   // illegal.
	OutConst = _rx * _rx * _ry * _ry + (_rx * _rx * _ry >> 1); // Constant as explaint above
	// To compensate for rounding
	xOld = x = rx;
	for (y = 0; y <= ry; y++)
	{
		if (y == ry)
			x = 0;
		else
		{
			SumY = ((uint32_t)(rx * rx)) * ((uint32_t)(y * y)); // Does not change in loop
			while (Sum = SumY + ((uint32_t)(ry * ry)) * ((uint32_t)(x * x)), (x > 0) && (Sum > OutConst))
				x--;
		}
		// Since we draw lines, we can not draw on the first iteration
		if (y)
		{
			LT268_TFT_DrawLine(x0 - xOld, y0 - y + 1, x0 - x, y0 - y, color);
			LT268_TFT_DrawLine(x0 - xOld, y0 + y - 1, x0 - x, y0 + y, color);
			LT268_TFT_DrawLine(x0 + xOld, y0 - y + 1, x0 + x, y0 - y, color);
			LT268_TFT_DrawLine(x0 + xOld, y0 + y - 1, x0 + x, y0 + y, color);
		}
		xOld = x;
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawEllipse_Fill
* Description  	: Draw a solid ellipse.
* Input        	: - x0,y0: central coordinate of ellipse
				  - rx,ry: ellipse radius in xy direction
				  - color: color of ellipse
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawEllipse_Fill(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, uint16_t color)
{
	uint32_t OutConst, Sum, SumY;
	uint16_t x, y;
	uint32_t _rx = rx;
	uint32_t _ry = ry;
	OutConst = _rx * _rx * _ry * _ry + (_rx * _rx * _ry >> 1); // Constant as explaint above
	// To compensate for rounding
	x = rx;
	for (y = 0; y <= ry; y++)
	{
		SumY = ((uint32_t)(rx * rx)) * ((uint32_t)(y * y)); // Does not change in loop
		while (Sum = SumY + ((uint32_t)(ry * ry)) * ((uint32_t)(x * x)), (x > 0) && (Sum > OutConst))
			x--;
		LT268_TFT_Draw_hline(x0 - x, y0 + y, 2 * x, color);
		if (y)
			LT268_TFT_Draw_hline(x0 - x, y0 - y, 2 * x, color);
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawEllipse_Width
* Description  	: Draw a solid ellipse with wireframe.
* Input        	: - x0,y0: central coordinate of ellipse
				  - rx,ry: ellipse radius in xy direction
				  - WidthColor: color of the wireframe
				  - BackgroundColor: color of the ellipse
				  - Width: Width of the wireframe
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawEllipse_Width(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, uint16_t WidthColor, uint16_t BackgroundColor, uint16_t Width)
{
	LT268_TFT_DrawEllipse_Fill(x0, y0, rx + Width, ry + Width, WidthColor);
	LT268_TFT_DrawEllipse_Fill(x0, y0, rx, ry, BackgroundColor);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawCylinder
* Description  	: Draw a solid cylinder with wireframe.
* Input        	: - XCenter,YCenter: bottom ellipse center coordinate
				  - X_R,Y_R: bottom ellipse radius in xy direction
				  - H: hight of the ellipse
				  - CylinderColor: color of the wireframe
				  - ForegroundColor: color of the cylinder
				  - Width: Width of the wireframe
* Output       	: None
* Return       	: None
*********************************************************************************/
uint8_t LT268_TFT_DrawCylinder(uint16_t XCenter, uint16_t YCenter, uint16_t X_R, uint16_t Y_R, uint16_t H, uint32_t CylinderColor, uint32_t ForegroundColor, uint8_t Width)
{
	uint8_t cut = 0;
	if (YCenter < H)
		return 1;
	// bottom ellipse
	LT268_TFT_DrawEllipse_Width(XCenter, YCenter, X_R, Y_R, CylinderColor, ForegroundColor, Width);

	// Middle rectangle
	LT268_TFT_DrawSquare_Fill(XCenter - X_R, YCenter - H, XCenter + X_R, YCenter, ForegroundColor);

	// Top ellipse
	LT268_TFT_DrawEllipse_Width(XCenter, YCenter - H, X_R, Y_R, CylinderColor, ForegroundColor, Width);

	if (Width >= 1)
	{
		cut = 1;
		LT268_TFT_DrawSquare_Fill(XCenter + X_R + cut, YCenter - H, XCenter + X_R + Width, YCenter, CylinderColor);
		LT268_TFT_DrawSquare_Fill(XCenter - X_R - Width, YCenter - H, XCenter - X_R - cut, YCenter, CylinderColor);
	}
	return 0;
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawTriangle
* Description  	: Draw a hollow triangle.
* Input        	: - x1,y1,x2,y2,x3,y3: point coordinate of triangle
				  - color: color of triangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)
{
	LT268_TFT_DrawLine(x1, y1, x2, y2, color);
	LT268_TFT_DrawLine(x1, y1, x3, y3, color);
	LT268_TFT_DrawLine(x2, y2, x3, y3, color);
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawTriangle
* Description  	: Draw a solid triangle.
* Input        	: - x1,y1,x2,y2,x3,y3: point coordinate of triangle
				  - color: color of triangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawTriangle_Fill(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)
{
	uint16_t t;
	int32_t xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int32_t incx, incy, uRow, uCol;

	uint16_t temp;
	if (y1 > y2)
	{
		temp = y2;
		y2 = y1;
		y1 = temp;
		temp = x2;
		x2 = x1;
		x1 = temp;
	}
	if (y1 > y3)
	{
		temp = y3;
		y3 = y1;
		y1 = temp;
		temp = x3;
		x3 = x1;
		x1 = temp;
	}
	if (x2 > x3)
	{
		temp = x3;
		x3 = x2;
		x2 = temp;
		temp = y3;
		y3 = y2;
		y2 = temp;
	}

	delta_x = x3 - x2; // Calculate coordinate increments
	delta_y = y3 - y2;
	uRow = x2;
	uCol = y2;
	// Set single step direction
	if (delta_x > 0)
		incx = 1;
	else if (delta_x == 0)
		incx = 0; // Vertical line
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}

	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; // horizon line
	else
	{
		incy = -1;
		delta_y = -delta_y;
	}
	// Select basic incremental coordinate axis
	if (delta_x > delta_y)
		distance = delta_x;
	else
		distance = delta_y;
	for (t = 0; t <= distance + 1; t++) // Line drawing output
	{
		LT268_TFT_DrawPoint(uRow, uCol, color); // Draw a point
		LT268_TFT_DrawLine(x1, y1, uRow, uCol, color);
		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

/********************************************************************************
* Function Name	: LT268_TFT_DrawTriangle_Frame
* Description  	: Draw a solid triangle with wireframe.
* Input        	: - x1,y1,x2,y2,x3,y3: point coordinate of triangle
				  - WidthColor: color of the wireframe
				  - BackgroundColor: color of the ellipse
				  - Width: Width of the wireframe
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawTriangle_Frame(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t WidthColor, uint16_t BackgroundColor)
{
	LT268_TFT_DrawTriangle_Fill(x1, y1, x2, y2, x3, y3, BackgroundColor);
	LT268_TFT_DrawTriangle(x1, y1, x2, y2, x3, y3, WidthColor);
}

/********************************************************************************
* Function Name	: LT268_TFT_MakeTable
* Description  	: Draw a table.
* Input        	: - X1,Y1: Start coordinate
				  - W: Width of each column
				  - H: Height of each row
				  - Line: number of row
				  - Row: number of column
				  - TableColor: Wireframe color
				  - ItemColor: Item bar background color
				  - ForegroundColor: Interior window background color
				  - width1: Inner frame width
				  - width2: Outer frame width
				  - mode: 0: Item bar vertical  1: Item bar horizontal
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_MakeTable(uint16_t X1, uint16_t Y1, uint16_t W, uint16_t H, uint16_t Line, uint16_t Row, uint32_t TableColor, uint32_t ItemColor, uint32_t ForegroundColor, uint16_t width1, uint16_t width2, uint8_t mode)
{
	uint16_t i = 0;
	uint16_t x2, y2;
	x2 = X1 + W * Row;
	y2 = Y1 + H * Line;

	LT268_TFT_DrawSquare_Width(X1, Y1, x2, y2, TableColor, ForegroundColor, width2);

	if (mode == 0)
		LT268_TFT_DrawSquare_Fill(X1, Y1, X1 + W, y2, ItemColor);
	else if (mode == 1)
		LT268_TFT_DrawSquare_Fill(X1, Y1, x2, Y1 + H, ItemColor);

	for (i = 0; i < Line; i++)
	{
		LT268_TFT_DrawLine_Width(X1, Y1 + i * H, x2, Y1 + i * H, TableColor, width1);
	}

	for (i = 0; i < Row; i++)
	{
		LT268_TFT_DrawLine_Width(X1 + i * W, Y1, X1 + i * W, y2, TableColor, width1);
	}
}

//----------------------------------------------------------------------Font----------------------------------------------------------------------
/********************************************************************************
* Function Name	: LT268_TFT_Show_Internal_Char
* Description  	: Display an internal ASCII encoded character.
* Input        	: - x,y: start displaying coordinates
				  - size_w,size_h: the width and height of the font
				  - disp_w: width to display
				  - mode: 0: with background  1: without background
				  - FontColor: font color
				  - BackGroundColor: font background
				  - num: an ASCII encoded character
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_Show_Internal_Char(uint16_t x, uint16_t y, uint8_t size_w, uint8_t size_h, uint8_t disp_w, uint8_t mode, uint16_t FontColor, uint16_t BackGroundColor, uint8_t num)
{
	uint8_t temp;
	uint16_t x0 = x, i, j, k;
	uint16_t x_buff = 0, y_buff = 0, csize;
	uint16_t disp_rowby, font_rowby;

	disp_rowby = (disp_w * 1 + 7) / 8;
	font_rowby = (size_w / 2 * 1 + 7) / 8;

	csize = font_rowby * size_h; // the number of bytes of a character corresponding to the lattice set

	num = num - ' '; // get the offset value(font take mold from ' ')

	if (mode == 1)
	{
		LT_getBackGround(x, y, disp_w, size_h, m_PngData, PIC_ON_BaseImg);
	}
	else
	{
		LT268_BG_to_Pure(0, 0, disp_w, m_PngData,
						disp_w, size_h, BackGroundColor);
	}

	for (i = 0; i < size_h; i++)
	{
		for (k = 0; k < disp_rowby; k++)
		{
			if (size_w == 12)
				temp = asc2_1206[num][i * font_rowby + k]; // use 1206 font
			else if (size_w == 16)
				temp = asc2_1608[num][i * font_rowby + k]; // use 1608 font
			else if (size_w == 24)
				temp = asc2_2412[num][i * font_rowby + k]; // use 2412 font
			else if (size_w == 32)
				temp = asc2_3216[num][i * font_rowby + k]; // use 3216 font
			else
				return; // unsupported size

			for (j = 0; j < 8; j++)
			{
				if (temp & 0x80)
//					LT268_TFT_DrawPoint_Buffer(x_buff, y_buff, FontColor, disp_w);
					LT268_BG_to_Pure(x_buff, y_buff, disp_w, m_PngData,
									 1, 1, FontColor);
				temp <<= 1;
				x_buff++;
				if (x_buff >= disp_w)
					break;
			}
		}
		x_buff = 0;
		y_buff++;
	}

	LT268_buffer_to_TFT(0, 0, disp_w, m_PngData,
						x, y, disp_w, size_h);
}

/********************************************************************************
* Function Name	: LT268_TFT_ShowAscll
* Description  	: Displays an internal ASCII encoded string.
* Input        	: - x,y: start displaying coordinates
				  - size: the size of the font
				  - mode: 0: with background  1: without background
				  - FontColor: font color
				  - BackGroundColor: font background
				  - *str: ASCII encoded string
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_ShowAscll(uint16_t x, uint16_t y, uint8_t size, uint8_t mode, uint16_t FontColor, uint16_t BackGroundColor, uint8_t *str)
{
	while ((*str <= '~') && (*str >= ' ')) // Judge whether it is an illegal character!
	{
		if (x + size / 2 > LCD_XSIZE_TFT)
		{
			x = 0;
			y += size;
		}
		if (y + size > LCD_YSIZE_TFT)
			break;
		LT268_TFT_Show_Internal_Char(x, y, size, size, size / 2, mode, FontColor, BackGroundColor, *str);

		x += size / 2;
		str++;
	}
}

/********************************************************************************
* Function Name	: LT268_GrayScaleFont_dislay
* Description  	: Display a grayscale font.
* Input        	: - type: 0:GB2312  1:GBK  2:BIG5  3:UNICODE  4:ASCII  6:UNICODE
				  - addr,font_w,font_h,gray: the address,width and high of the font
				  - gray: 0/1/2 = 2/4/16 grayScale
				  - FColor,BColor: color of font and background
				  - enbackcolor: 0: without background  1: with background
				  - mix,mixpic:  0:with fullscreen interface   1:with specific pictures(Text font needs to be fully included)
				  - tft_x,tft_y: start displaying coordinates
				  - disp_w: width to display
				  - *c: string
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_GrayScaleFont_dislay(uint8_t type, uint8_t layn, uint32_t addr, uint8_t font_w, uint8_t font_h, uint8_t gray,
								uint16_t FColor, uint16_t BColor, uint8_t enbackcolor, uint8_t mix, _PICINFO mixpic,
								uint16_t tft_x, uint16_t tft_y, uint16_t disp_w, uint8_t *c)
{
	uint8_t temp, temd;
	uint16_t i, j, k;
	uint16_t x = 0, y = 0, csize;
	uint16_t disp_rowby, font_rowby, data_w;
	uint16_t buff_x = 0, buff_y = 0;
	uint16_t temp_ALL, temp_H, temp_L;
	uint16_t gray_bit;

	uint16_t R0 = 0, G0 = 0, B0 = 0, val;
	uint16_t R1 = 0, G1 = 0, B1 = 0;
	uint16_t R2 = 0, G2 = 0, B2 = 0;
	uint32_t pixel_color;
	//	printf(" enbackcolor   %d %d   \r\n",enbackcolor,mix);
	//	disp_w = font_w;

	// background
	if (enbackcolor)
	{
		LT268_BG_to_Pure(0, 0, disp_w, m_PngData,
						disp_w, font_h, BColor);
	}
	else
	{
		if (mix == 0)
		{
			if(layn == PIC_ON_LCDImg)
			{
				LT_getBackGround(tft_x, tft_y, disp_w, font_h, m_PngData,PIC_ON_LCDImg);
			}
			else
			{
				LT_getBackGround(tft_x, tft_y, disp_w, font_h, m_PngData, PIC_ON_BaseImg);
			}
		}
		else
		{
			if (mixpic.flag == 0x10)
//				LT268_TFT_FillColor_Buffer2(0, 0, disp_w, m_PngData,
//								disp_w, font_h, FullScreen_color);
				LT268_BG_to_Pure(0, 0, disp_w, m_PngData,
								disp_w, font_h, mixpic.len);
			else
			{
				if(mixpic.flag == 3)
				{
					LT_getBackGround(tft_x, tft_y, disp_w, font_h, m_PngData, PIC_ON_BaseImg);
				}
				else
				{
					if (mixpic.flag == 1 || mixpic.flag == 2)
					LT_getBackGround(tft_x, tft_y, disp_w, font_h, m_PngData, PIC_ON_BaseImg);
					
					LT268_pic_to_buffer(0, 0, disp_w, m_PngData, tft_x - mixpic.x, tft_y - mixpic.y, mixpic.w, mixpic.addr, disp_w, font_h, mixpic.flag);
				}
			}

		}
	}

	if (gray == 0)
		gray_bit = 1;
	else if (gray == 1)
	{
		gray_bit = 2;

		R0 = (FColor >> 11) & 0x1F;
		G0 = (FColor >> 5) & 0x3F;
		B0 = (FColor)&0x1F;
		if (enbackcolor)
		{
			R1 = (BColor >> 11) & 0x1F;
			G1 = (BColor >> 5) & 0x3F;
			B1 = (BColor)&0x1F;
		}
	}
	else if (gray == 2)
	{
		gray_bit = 4;

		R0 = (FColor >> 11) & 0x1F;
		G0 = (FColor >> 5) & 0x3F;
		B0 = (FColor)&0x1F;
		if (enbackcolor)
		{
			R1 = (BColor >> 11) & 0x1F;
			G1 = (BColor >> 5) & 0x3F;
			B1 = (BColor)&0x1F;
		}
	}
	if (disp_w > font_w)
		data_w = font_w; // The displayed width is smaller than the font width
	else
		data_w = disp_w;
	disp_rowby = (data_w * gray_bit + 7) / 8; // The number of bytes for display a line of text
	font_rowby = (font_w * gray_bit + 7) / 8; // The number of bytes of display a line of text

	if (type == 4)
	{
		addr += (104 + (c[0] - 0x20) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 0)
	{
		temp_ALL = ((c[0] - 0xa1) & 0x00ff) * 94 + c[1] - 0xa1;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 1)
	{
		temp_H = (c[0] - 0x81) * 190;
		if (c[1] <= 0x7F)
			temp_L = c[1] - 0x40;
		else if (c[1] > 0x7F)
			temp_L = c[1] - 0x40 - 1;
		temp_ALL = temp_H + temp_L;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 2)
	{
		temp_H = ((c[0] - 0xa1) & 0x00ff) * 160;
		if (c[1] >= 0x40 && c[1] <= 0x7F)
			temp_L = c[1] - 0x40;
		else if (c[1] >= 0xA0 && c[1] <= 0xFF)
			temp_L = c[1] - 0xA0 + 64;
		temp_ALL = temp_H + temp_L;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 3)
	{
		uint16_t unicode_temp = (uint16_t)&c[0];

		addr += (104 + (95 + unicode_temp) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 6)
	{
		uint16_t unicode_temp = (uint16_t)&c[0];

		addr += (104 + 95 * font_rowby * font_h + unicode_temp * (font_rowby * font_h + 1) +1);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}

	// buffer
	if (gray_bit == 1)
	{
		for (i = 0; i < font_h; i++)
		{
			for (k = 0; k < disp_rowby; k++)
			{
				temp = DMA_txbuf1[i * font_rowby + k];
				for (j = 0; j < 8; j++)
				{
					if (temp & 0x80)
//						LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, disp_w);
						LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
										 1, 1, FColor);
					temp <<= 1;
					buff_x++;
					if (buff_x >= disp_w)
					{
						k = disp_rowby;
						break;
					}
				}
			}
			buff_x = 0;
			buff_y++;
		}
	}
	else if (gray_bit == 2)
	{
		if (enbackcolor)
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 4; j++)
					{
						temd = ((temp >> 6) & 0x03);

						if (temd == 3)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 3)
						{
							R2 = ((R0 * temd + R1 * (4 - temd)) / 4);
							G2 = ((G0 * temd + G1 * (4 - temd)) / 4);
							B2 = ((B0 * temd + B1 * (4 - temd)) / 4);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, pixel_color);
						}
						temp <<= 2;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = 0;
				buff_y++;
			}
		}
		else
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 4; j++)
					{
						temd = ((temp >> 6) & 0x03);

						if (temd == 3)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 3)
						{
#if (LT_PIC_BYTE_SWAP==1)
							R1 = ((m_PngData[(i * disp_w + k * 4 + j) * 2 + 0] >> 3) & 0x1F);
							G1 = (((m_PngData[(i * disp_w + k * 4 + j) * 2 + 0] & 0x07) << 3) | (m_PngData[(i * disp_w + k * 4 + j) * 2 + 1] >> 5));
							B1 = (m_PngData[(i * disp_w + k * 4 + j) * 2 + 1] & 0x1F);
#else
							R1 = ((m_PngData[(i * disp_w + k * 4 + j) * 2 + 1] >> 3) & 0x1F);
							G1 = (((m_PngData[(i * disp_w + k * 4 + j) * 2 + 1] & 0x07) << 3) | (m_PngData[(i * disp_w + k * 4 + j) * 2 + 0] >> 5));
							B1 = (m_PngData[(i * disp_w + k * 4 + j) * 2 + 0] & 0x1F);
#endif
							R2 = ((R0 * temd + R1 * (4 - temd)) / 4);
							G2 = ((G0 * temd + G1 * (4 - temd)) / 4);
							B2 = ((B0 * temd + B1 * (4 - temd)) / 4);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 2;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = 0;
				buff_y++;
			}
		}
	}
	else if (gray_bit == 4)
	{
		if (enbackcolor)
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 2; j++)
					{
						temd = ((temp >> 4) & 0x0F);

						if (temd == 15)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 15)
						{
							R2 = ((R0 * temd + R1 * (15 - temd)) / 15);
							G2 = ((G0 * temd + G1 * (15 - temd)) / 15);
							B2 = ((B0 * temd + B1 * (15 - temd)) / 15);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 4;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = 0;
				buff_y++;
			}
		}
		else
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 2; j++)
					{
						temd = ((temp >> 4) & 0x0F);

						if (temd == 15)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 15)
						{
#if (LT_PIC_BYTE_SWAP==1)
							R1 = ((m_PngData[(i * disp_w + k * 2 + j) * 2 + 0] >> 3) & 0x1F);
							G1 = (((m_PngData[(i * disp_w + k * 2 + j) * 2 + 0] & 0x07) << 3) | (m_PngData[(i * disp_w + k * 2 + j) * 2 + 1] >> 5));
							B1 = (m_PngData[(i * disp_w + k * 2 + j) * 2 + 1] & 0x1F);
#else
							R1 = ((m_PngData[(i * disp_w + k * 2 + j) * 2 + 1] >> 3) & 0x1F);
							G1 = (((m_PngData[(i * disp_w + k * 2 + j) * 2 + 1] & 0x07) << 3) | (m_PngData[(i * disp_w + k * 2 + j) * 2 + 0] >> 5));
							B1 = (m_PngData[(i * disp_w + k * 2 + j) * 2 + 0] & 0x1F);
#endif
							R2 = ((R0 * temd + R1 * (15 - temd)) / 15);
							G2 = ((G0 * temd + G1 * (15 - temd)) / 15);
							B2 = ((B0 * temd + B1 * (15 - temd)) / 15);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, disp_w);
							LT268_BG_to_Pure(buff_x, buff_y, disp_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 4;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = 0;
				buff_y++;
			}
		}
	}

	// show
	LT268_buffer_to_TFT(0, 0, disp_w, m_PngData,
						tft_x, tft_y, disp_w, font_h);
}

/********************************************************************************
* Function Name	: LT268_GrayScaleFont_dislay_BUFF
* Description  	: Buffer a grayscale font.
* Input        	: - type: 0:GB2312  1:GBK  2:BIG5  3:UNICODE  4:ASCII  6:UNICODE
				  - addr,font_w,font_h: the address,width and high of the font
				  - gray: 0/1/2 = 2/4/16 grayScale
				  - FColor,BColor: color of font and background
				  - enbackcolor: 0: without background  1: with background
				  - disp_w: width to display
				  - *c: string
				  - buf_x,buf_y: position of font in buffer
				  - buf_w,*buf: width and starts address of buffer
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_GrayScaleFont_dislay_BUFF(uint8_t type, uint32_t addr, uint8_t font_w, uint8_t font_h, uint8_t gray,
									 uint16_t FColor, uint16_t BColor, uint8_t enbackcolor, uint16_t disp_w, uint8_t *c,
									 uint16_t buf_x, uint16_t buf_y, uint16_t buf_w, uint8_t *buf)
{
	uint8_t temp, temd;
	uint16_t i, j, k;
	uint16_t x = 0, y = 0, csize;
	uint16_t disp_rowby, font_rowby, data_w;
	uint16_t buff_x = buf_x, buff_y = buf_y;
	uint16_t temp_ALL, temp_H, temp_L;
	uint16_t gray_bit;

	uint16_t R0 = 0, G0 = 0, B0 = 0, val;
	uint16_t R1 = 0, G1 = 0, B1 = 0;
	uint16_t R2 = 0, G2 = 0, B2 = 0;
	uint32_t pixel_color;
	//	disp_w = font_w;

	if (gray == 0)
		gray_bit = 1;
	else if (gray == 1)
	{
		gray_bit = 2;

		R0 = (FColor >> 11) & 0x1F;
		G0 = (FColor >> 5) & 0x3F;
		B0 = (FColor)&0x1F;
		if (enbackcolor)
		{
			R1 = (BColor >> 11) & 0x1F;
			G1 = (BColor >> 5) & 0x3F;
			B1 = (BColor)&0x1F;
		}
	}
	else if (gray == 2)
	{
		gray_bit = 4;

		R0 = (FColor >> 11) & 0x1F;
		G0 = (FColor >> 5) & 0x3F;
		B0 = (FColor)&0x1F;
		if (enbackcolor)
		{
			R1 = (BColor >> 11) & 0x1F;
			G1 = (BColor >> 5) & 0x3F;
			B1 = (BColor)&0x1F;
		}
	}

	if (disp_w > font_w)
		data_w = font_w; // The displayed width is smaller than the font width
	else
		data_w = disp_w;
	disp_w += buf_x;
	disp_rowby = (data_w * gray_bit + 7) / 8; //  The number of bytes for display a line of text
	font_rowby = (font_w * gray_bit + 7) / 8; // The number of bytes of display a line of text
	//							printf(" font_rowby   %d %d %d \r\n",font_rowby,font_w,font_h);

	if (type == 4)
	{
		addr += (104 + (c[0] - 0x20) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 0)
	{
		temp_ALL = ((c[0] - 0xa1) & 0x00ff) * 94 + c[1] - 0xa1;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 1)
	{
		temp_H = (c[0] - 0x81) * 190;
		if (c[1] <= 0x7F)
			temp_L = c[1] - 0x40;
		else if (c[1] > 0x7F)
			temp_L = c[1] - 0x40 - 1;
		temp_ALL = temp_H + temp_L;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 2)
	{
		temp_H = ((c[0] - 0xa1) & 0x00ff) * 160;
		if (c[1] >= 0x40 && c[1] <= 0x7F)
			temp_L = c[1] - 0x40;
		else if (c[1] >= 0xA0 && c[1] <= 0xFF)
			temp_L = c[1] - 0xA0 + 64;
		temp_ALL = temp_H + temp_L;
		addr += (104 + (95 + temp_ALL) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 3)
	{
		uint16_t unicode_temp = (uint16_t)&c[0];

		addr += (104 + (95 + unicode_temp) * font_rowby * font_h);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}
	else if (type == 6)
	{
		uint16_t unicode_temp = (uint16_t)&c[0];

		addr += (104 + 95 * font_rowby * font_h + unicode_temp * (font_rowby * font_h + 1) + 1);
		LT_ReadFlash_UI(DMA_txbuf1, addr, font_rowby * font_h);
	}

	// buffer
	if (gray_bit == 1)
	{
		for (i = 0; i < font_h; i++)
		{
			for (k = 0; k < disp_rowby; k++)
			{
				temp = DMA_txbuf1[i * font_rowby + k];
				for (j = 0; j < 8; j++)
				{
					if (temp & 0x80)
//						LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, buf_w);
						LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
										 1, 1, FColor);
					temp <<= 1;
					buff_x++;
					if (buff_x >= disp_w)
					{
						k = disp_rowby;
						break;
					}
				}
			}
			buff_x = buf_x;
			buff_y++;
		}
	}
	else if (gray_bit == 2)
	{
		if (enbackcolor)
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 4; j++)
					{
						temd = ((temp >> 6) & 0x03);

						if (temd == 3)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 3)
						{
							R2 = ((R0 * temd + R1 * (4 - temd)) / 4);
							G2 = ((G0 * temd + G1 * (4 - temd)) / 4);
							B2 = ((B0 * temd + B1 * (4 - temd)) / 4);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 2;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = buf_x;
				buff_y++;
			}
		}
		else
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 4; j++)
					{
						temd = ((temp >> 6) & 0x03);

						if (temd == 3)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 3)
						{
#if (LT_PIC_BYTE_SWAP==1)
							R1 = ((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 0] >> 3) & 0x1F);
							G1 = (((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 0] & 0x07) << 3) | (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 1] >> 5));
							B1 = (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 1] & 0x1F);
#else
							R1 = ((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 1] >> 3) & 0x1F);
							G1 = (((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 1] & 0x07) << 3) | (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 0] >> 5));
							B1 = (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 4 + j) * 2 + 0] & 0x1F);
#endif
							R2 = ((R0 * temd + R1 * (4 - temd)) / 4);
							G2 = ((G0 * temd + G1 * (4 - temd)) / 4);
							B2 = ((B0 * temd + B1 * (4 - temd)) / 4);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 2;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = buf_x;
				buff_y++;
			}
		}
	}
	else if (gray_bit == 4)
	{
		if (enbackcolor)
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 2; j++)
					{
						temd = ((temp >> 4) & 0x0F);

						if (temd == 15)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 15)
						{
							R2 = ((R0 * temd + R1 * (15 - temd)) / 15);
							G2 = ((G0 * temd + G1 * (15 - temd)) / 15);
							B2 = ((B0 * temd + B1 * (15 - temd)) / 15);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 4;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = buf_x;
				buff_y++;
			}
		}
		else
		{
			for (i = 0; i < font_h; i++)
			{
				for (k = 0; k < disp_rowby; k++)
				{
					temp = DMA_txbuf1[i * font_rowby + k];
					for (j = 0; j < 2; j++)
					{
						temd = ((temp >> 4) & 0x0F);

						if (temd == 15)
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, FColor, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, FColor);
						else if (temd < 15)
						{
#if (LT_PIC_BYTE_SWAP==1)
							R1 = ((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 0] >> 3) & 0x1F);
							G1 = (((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 0] & 0x07) << 3) | (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 1] >> 5));
							B1 = (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 1] & 0x1F);
#else
							R1 = ((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 1] >> 3) & 0x1F);
							G1 = (((m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 1] & 0x07) << 3) | (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 0] >> 5));
							B1 = (m_PngData[(buf_x + buf_y * buf_w + i * buf_w + k * 2 + j) * 2 + 0] & 0x1F);
#endif
							R2 = ((R0 * temd + R1 * (15 - temd)) / 15);
							G2 = ((G0 * temd + G1 * (15 - temd)) / 15);
							B2 = ((B0 * temd + B1 * (15 - temd)) / 15);
							pixel_color = (R2 << 11) | (G2 << 5) | (B2);
//							LT268_TFT_DrawPoint_Buffer(buff_x, buff_y, pixel_color, buf_w);
							LT268_BG_to_Pure(buff_x, buff_y, buf_w, m_PngData,
											 1, 1, pixel_color);
						}

						temp <<= 4;
						buff_x++;
						if (buff_x >= disp_w)
						{
							k = disp_rowby;
							break;
						}
					}
				}
				buff_x = buf_x;
				buff_y++;
			}
		}
	}
}

void disp_V_Gray(void)
{
	int32_t i;
	int32_t w0; //,w1;
	int32_t h0; //,h1;

	uint32_t c;

	w0 = LCD_XSIZE_TFT / 3;
	h0 = LCD_YSIZE_TFT / 32;

	for (i = 0; i < 31; i++)
	{
		c = 31 - i;
		LT268_TFT_DrawSquare_Fill(0, h0 * i, w0 - 1, h0 * (i + 1), (c << 11) & 0xF800);
	}
	c = 0;
	LT268_TFT_DrawSquare_Fill(0, h0 * 31, w0 - 1, LCD_YSIZE_TFT - 1, c);

	h0 = LCD_YSIZE_TFT / 64;
	for (i = 0; i < 63; i++)
	{
		c = 63 - i;
		LT268_TFT_DrawSquare_Fill(w0, h0 * i, w0 * 2 - 1, h0 * (i + 1), (c << 5) & 0x7E0);
	}
	c = 0;
	LT268_TFT_DrawSquare_Fill(w0, h0 * 63, w0 * 2 - 1, LCD_YSIZE_TFT - 1, c);

	h0 = LCD_YSIZE_TFT / 32;

	for (i = 0; i < 31; i++)
	{
		c = 31 - i;
		LT268_TFT_DrawSquare_Fill(w0 * 2, h0 * i, LCD_XSIZE_TFT - 1, h0 * (i + 1), c & 0x1F);
	}
	c = 0;
	LT268_TFT_DrawSquare_Fill(w0 * 2, h0 * 31, LCD_XSIZE_TFT - 1, LCD_YSIZE_TFT - 1, c);
}

//-----------------------------------------Buffer model------------------------------------------------------------------------
/********************************************************************************
* Function Name	: LT268_TFT_DrawPoint_Buffer
* Description  	: Draw a point on the buffer.
* Input        	: - x,y: coordinates of point on the buffer
				  - color: point color
				  - canvas_w: buffer width
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_DrawPoint_Buffer(uint16_t x, uint16_t y, uint16_t color, uint16_t canvas_w)
{
	
#if (LT_PIC_BYTE_SWAP==1)
	if (y * 2 * canvas_w + 2 * x + 1 < MAX_PixelSize - 1)
	{
		m_PngData[y * 2 * canvas_w + 2 * x + 0] = color>>8;
		m_PngData[y * 2 * canvas_w + 2 * x + 1] = color;
	}
#else
	if (y * 2 * canvas_w + 2 * x + 1 < MAX_PixelSize - 1)
	{
		m_PngData[y * 2 * canvas_w + 2 * x + 0] = color;
		m_PngData[y * 2 * canvas_w + 2 * x + 1] = color>>8;
	}
#endif	
}

/********************************************************************************
* Function Name	: LT268_TFT_FillColor_Buffer2
* Description  	: Draw a solid rectangle on the buffer.
* Input        	: - buf_x,buf_y: The coordinates of the rectangle on the buffer
				  - buf_w,*m_Data: buffer width and address
				  - Width,High,color: Width,High and color of rectangle
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_TFT_FillColor_Buffer2(uint16_t buf_x, uint16_t buf_y, uint16_t buf_w, uint8_t *m_Data, uint16_t Width, uint16_t High, uint16_t color)
{
	uint32_t j, k;
	uint16_t *p16_buf = (uint16_t *)m_Data;

#if (LT_PIC_BYTE_SWAP==1)
	for (j = 0; j < High; j++)
	{
		for (k = 0; k < Width; k++)
		{
//			p16_buf[(buf_y + j) * buf_w + buf_x + k] = color;
			m_Data[(buf_y+j)*buf_w*2 + buf_x*2 + 2*k + 0] = color>>8;
			m_Data[(buf_y+j)*buf_w*2 + buf_x*2 + 2*k + 1] = color;
		}
	}
#else
	for (j = 0; j < High; j++)
	{
		for (k = 0; k < Width; k++)
		{
			p16_buf[(buf_y + j) * buf_w + buf_x + k] = color;
		}
	}
#endif	
}

void LT268_TFT_Draw_hline_Buffer(uint16_t x0, uint16_t y0, uint16_t len, uint16_t color, uint16_t canvas_w)
{
	if ((len == 0) || (x0 > LCD_XSIZE_TFT - 1) || (y0 > LCD_YSIZE_TFT - 1))
		return;
	LT268_TFT_FillColor_Buffer2(x0, y0, canvas_w, m_PngData,
								len, 1, color);
	
}

void LT268_TFT_DrawLine_Buffer(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, uint16_t canvas_w)
{
	uint16_t t;
	int32_t xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int32_t incx, incy, uRow, uCol;
	delta_x = x2 - x1; // Calculate coordinate increments
	delta_y = y2 - y1;
	uRow = x1;
	uCol = y1;
	// Set single step direction
	if (delta_x > 0)
		incx = 1;
	else if (delta_x == 0)
		incx = 0; // Vertical line
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}

	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; // horizon line
	else
	{
		incy = -1;
		delta_y = -delta_y;
	}
	// Select basic incremental coordinate axis
	if (delta_x > delta_y)
		distance = delta_x;
	else
		distance = delta_y;
	for (t = 0; t <= distance + 1; t++) // Line drawing output
	{
		LT268_TFT_DrawPoint_Buffer(uRow, uCol, color, canvas_w); // Draw a point
		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

void LT268_TFT_DrawLine_Width_Buffer(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, uint16_t Width, uint16_t canvas_w)
{
	uint16_t i = 0;

	if (x2 == x1)
	{
		while (Width--)
		{
			LT268_TFT_DrawLine_Buffer(x1 + i, y1, x2 + i, y2, color, canvas_w);
			i++;
		}
	}
	else if (y2 == y1)
	{
		while (Width--)
		{
			LT268_TFT_DrawLine_Buffer(x1, y1 - i, x2, y2 - i, color, canvas_w);
			i++;
		}
	}
	else
	{
		while (Width--)
		{
			LT268_TFT_DrawLine_Buffer(x1 + i, y1, x2 + i, y2, color, canvas_w);
			i++;
		}
	}
}

void LT268_TFT_DrawSquare_Fill_Buffer(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color, uint16_t canvas_w)
{
	uint16_t temp = 0;
	if (y1 > y2)
	{
		temp = y1;
		y1 = y2;
		y2 = temp;
	}
	if (x1 > x2)
	{
		temp = x1;
		x1 = x2;
		x2 = temp;
	}
	LT268_TFT_FillColor_Buffer2(x1, y1, canvas_w, m_PngData,
								x2 - x1 + 1, y2 - y1 + 1, color);
}

void LT268_DrawTriangle_Fill_Buffer(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color, uint16_t canvas_w)
{
	uint16_t t;
	int32_t xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int32_t incx, incy, uRow, uCol;

	uint16_t temp;
	if (y1 > y2)
	{
		temp = y2;
		y2 = y1;
		y1 = temp;
		temp = x2;
		x2 = x1;
		x1 = temp;
	}
	if (y1 > y3)
	{
		temp = y3;
		y3 = y1;
		y1 = temp;
		temp = x3;
		x3 = x1;
		x1 = temp;
	}
	if (x2 > x3)
	{
		temp = x3;
		x3 = x2;
		x2 = temp;
		temp = y3;
		y3 = y2;
		y2 = temp;
	}

	delta_x = x3 - x2; // Calculate coordinate increments
	delta_y = y3 - y2;
	uRow = x2;
	uCol = y2;
	// Set single step direction
	if (delta_x > 0)
		incx = 1;
	else if (delta_x == 0)
		incx = 0; // Vertical line
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}

	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; // horizon line
	else
	{
		incy = -1;
		delta_y = -delta_y;
	}
	// Select basic incremental coordinate axis
	if (delta_x > delta_y)
		distance = delta_x;
	else
		distance = delta_y;
	for (t = 0; t <= distance + 1; t++) //  Line drawing output
	{
		LT268_TFT_DrawPoint_Buffer(uRow, uCol, color, canvas_w); // // Draw a point
		LT268_TFT_DrawLine_Buffer(x1, y1, uRow, uCol, color, canvas_w);

		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

void LT268_TFT_DrawCircle_Fill_Buffer(uint16_t xc, uint16_t yc, uint16_t r, uint16_t color, uint16_t canvas_w)
{
	uint32_t i;
	uint32_t imax = ((uint32_t)r * 707) / 1000 + 1;
	uint32_t sqmax = (uint32_t)r * (uint32_t)r + (uint32_t)r / 2;
	uint32_t x = r;
	LT268_TFT_Draw_hline_Buffer(xc - r, yc, 2 * r, color, canvas_w);
	for (i = 1; i <= imax; i++)
	{
		if ((i * i + x * x) > sqmax)
		{
			// draw lines from outside
			if (x > imax)
			{
				LT268_TFT_Draw_hline_Buffer(xc - i + 1, yc + x, 2 * (i - 1), color, canvas_w);
				LT268_TFT_Draw_hline_Buffer(xc - i + 1, yc - x, 2 * (i - 1), color, canvas_w);
			}
			x--;
		}
		// draw lines from inside (center)
		LT268_TFT_Draw_hline_Buffer(xc - x, yc + i, 2 * x, color, canvas_w);
		LT268_TFT_Draw_hline_Buffer(xc - x, yc - i, 2 * x, color, canvas_w);
	}
}

/********************************************************************************
* Function Name	: LT268_DrawPoint_Buffer_alphablend
* Description  	: Draw a point on the buffer according to the alpha.
* Input        	: - x,y: coordinates of point on the buffer
				  - alpha: alpha of color(float 0~1)
				  - color: point color
				  - canvas_w: buffer width
* Output       	: None
* Return       	: None
*********************************************************************************/
void LT268_DrawPoint_Buffer_alphablend(int32_t x, int32_t y, float alpha, uint32_t color, uint16_t canvas)
{
	if (alpha == 1)
		LT268_TFT_DrawPoint_Buffer(x, y, color, canvas);
	else if (alpha > 0)
	{
		uint16_t R0 = 0, G0 = 0, B0 = 0, val;
		uint16_t R1 = 0, G1 = 0, B1 = 0;
		uint16_t R2 = 0, G2 = 0, B2 = 0;
		uint32_t new_color;

		R0 = (color >> 11) & 0x1F;
		G0 = (color >> 5) & 0x3F;
		B0 = (color)&0x1F;
		R1 = (p16_m_PngData[x + y * canvas] >> 11) & 0x1F;
		G1 = (p16_m_PngData[x + y * canvas] >> 5) & 0x3F;
		B1 = (p16_m_PngData[x + y * canvas]) & 0x1F;

		R2 = R1 * (1 - alpha) + R0 * alpha;
		G2 = G1 * (1 - alpha) + G0 * alpha;
		B2 = B1 * (1 - alpha) + B0 * alpha;

		new_color = (R2 << 11) | (G2 << 5) | (B2);
		LT268_TFT_DrawPoint_Buffer(x, y, new_color, canvas);
	}
}

/********************************************************************************
* Function Name	: line_k_compare
* Description  	: Compare the slope of two straight lines.
* Input        	: - x0,y0: intersection point of two lines
				  - x1,y1,x2,y2: two points on two lines
* Output       	: 1:k2 > k1
* Return       	: None
*********************************************************************************/
uint8_t line_k_compare(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
	if ((y1 - y0) * (x2 - x0) < (y2 - y0) * (x1 - x0))
		return 1; // k2 > k1
	else
		return 0;
}
float line_k(float x0, float y0, float x1, float y1)
{
	return ((y1 - y0)/(x1 - x0)); // k2 > k1
}

#define max(a,b)	(((a) > (b)) ? (a) : (b))
uint8_t GetOverlapPart_rect(uint16_t ax, uint16_t ay, uint16_t aw, uint16_t ah, uint16_t *cx, uint16_t *cy, uint16_t *cw, uint16_t *ch)
{
//	uint16_t ax,ay,bx,by,cx,cy,dx,dy;
	uint16_t bx,by,dx,dy;

	bx = ax + aw -1;
	by = ay + ah -1;

	dx = *cx + *cw -1;
	dy = *cy + *ch -1;
	
	*cx = max(ax, *cx);
	*cy = max(ay, *cy); 
	*cw = min(bx, dx);
	*ch = min(by, dy); 
}

